package com.nineclock.system.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.nineclock.common.constant.SMSConstant;
import com.nineclock.common.entity.PageResult;
import com.nineclock.common.enums.ResponseEnum;
import com.nineclock.common.exception.NcException;
import com.nineclock.common.threadlocal.CurrentUserHolder;
import com.nineclock.common.utils.BeanHelper;
import com.nineclock.system.dto.SysChangeMainManagerDTO;
import com.nineclock.system.dto.SysCompanyUserDTO;
import com.nineclock.system.dto.SysRoleDTO;
import com.nineclock.system.entity.ExcelMember;
import com.nineclock.system.entity.ExcelMemberListener;
import com.nineclock.system.mapper.*;
import com.nineclock.system.pojo.*;
import com.nineclock.system.service.SmsService;
import com.nineclock.system.service.SysCompanyUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 黑马程序员
 * @Company http://www.ithiema.com
 * @Version 1.0
 */
@Service
@Slf4j
public class SysCompanyUserServiceImpl implements SysCompanyUserService {

    @Autowired
    SysCompanyUserMapper companyUserMapper;

    @Autowired
    SysRoleMapper roleMapper;

    @Autowired
    SmsService smsService;

    @Override
    public List<SysCompanyUserDTO> queryCompanyUser(Long companyId, Long userId) {
        //健壮性的判断(最少传一个)
        if(companyId == null && userId == null){
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        LambdaQueryWrapper<SysCompanyUser> companyUserQw = new LambdaQueryWrapper<>();
        if(companyId != null){
            companyUserQw.eq(SysCompanyUser::getCompanyId, companyId);
        }
        if(userId != null){
            companyUserQw.eq(SysCompanyUser::getUserId, userId);
        }
        //查询可用的企业员工
        companyUserQw.eq(SysCompanyUser::getEnable, 1);

        List<SysCompanyUser> companyUserList = companyUserMapper.selectList(companyUserQw);
        if(CollectionUtil.isEmpty(companyUserList)){
            throw new NcException(ResponseEnum.USER_NOT_JOIN_COMPANY);
        }

        //转换为 dto对象
        List<SysCompanyUserDTO> companyUserDTOList = BeanHelper.copyWithCollection(companyUserList, SysCompanyUserDTO.class);
        //给每一个员工查询角色信息
        for (SysCompanyUserDTO companyUserDTO : companyUserDTOList) {
            //根据员工id查询关联的角色信息
            List<SysRole> roleList = roleMapper.queryRolesByUserIdAndCompanyId(companyUserDTO.getId(), companyUserDTO.getCompanyId());

            if(CollectionUtil.isEmpty(roleList)){
                companyUserDTO.setRoles(new ArrayList<>());
            }else{
                companyUserDTO.setRoles(BeanHelper.copyWithCollection(roleList, SysRoleDTO.class));
            }
        }

        return companyUserDTOList;
    }

    /**
     * 获取的是 当前企业的主管理员
     * @return
     */
    @Override
    public SysCompanyUserDTO getCurrentAdmin() {
        //获取当前登录企业的 id
        Long companyId = CurrentUserHolder.get().getCompanyId();

        SysCompanyUser companyUser = companyUserMapper.queryCurrentAdmin(companyId);

        if(companyUser == null){
            throw new NcException(ResponseEnum.COMPANY_ADMIN_NOT_EXISTS);
        }

        SysCompanyUserDTO companyUserDTO = BeanHelper.copyProperties(companyUser, SysCompanyUserDTO.class);
        return companyUserDTO;
    }

    /**
     * 查询 当前企业下所有的员工列表
     * @return
     */
    @Override
    public List<SysCompanyUserDTO> queryCompanyMemberList() {
        //获取当前登录的 企业id
        Long companyId = CurrentUserHolder.get().getCompanyId();
        //查询员工列表
        LambdaQueryWrapper<SysCompanyUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysCompanyUser::getCompanyId, companyId); //企业
        wrapper.eq(SysCompanyUser::getEnable, 1); //有效的

        List<SysCompanyUser> companyUserList = companyUserMapper.selectList(wrapper);

        if(CollectionUtil.isEmpty(companyUserList)){
            throw new NcException(ResponseEnum.USER_NOT_FOUND);
        }

        return BeanHelper.copyWithCollection(companyUserList, SysCompanyUserDTO.class);
    }

    @Autowired
    SysCompanyUserRoleMapper companyUserRoleMapper;

    /**
     * 1. 健壮性的判断
     * 2. 查询新管理员 是否存在
     * 3. 校验验证码
     * 4. 删除原来的主管理员的身份
     * 5. 添加新的主管理员的身份
     *
     * @param changeMainManagerDTO
     */
    @Override
    public void changeSysAdmin(SysChangeMainManagerDTO changeMainManagerDTO) {
        //1. 健壮性的判断
        if(changeMainManagerDTO == null || changeMainManagerDTO.getCode() == null || changeMainManagerDTO.getUserId() == null){
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }
        //2. 查询新管理员 是否存在
        SysCompanyUser companyUser = companyUserMapper.selectById(changeMainManagerDTO.getUserId());
        if(companyUser == null){
            throw new NcException(ResponseEnum.USER_NOT_FOUND);
        }
        //3. 校验验证码
        Boolean flag =
                smsService.verify(companyUser.getMobile(),
                        SMSConstant.SMS_TYPE_CHANGE_MANAGER,
                        changeMainManagerDTO.getCode());
        if(!flag){
            throw new NcException(ResponseEnum.INVALID_VERIFY_CODE);
        }


        //4. 删除原来的主管理员的身份
        //4.1 获取当前企业 主管理员角色对应的id
        LambdaQueryWrapper<SysRole> roleQw = new LambdaQueryWrapper<>();
        roleQw.eq(SysRole::getCompanyId, CurrentUserHolder.get().getCompanyId());
        roleQw.eq(SysRole::getRoleName, "ROLE_ADMIN_SYS");

        SysRole role = roleMapper.selectOne(roleQw);
        if(role == null){
            throw new NcException(ResponseEnum.ROLE_NOT_FOUND);
        }

        //4.2 删除原来主管理员 的关系
        //获取原来的主管理员
        SysCompanyUser adminUser = companyUserMapper.queryCurrentAdmin(CurrentUserHolder.get().getCompanyId());
        LambdaQueryWrapper<SysCompanyUserRole> companyUserRoleQw = new LambdaQueryWrapper<>();
        companyUserRoleQw.eq(SysCompanyUserRole::getCompanyId, CurrentUserHolder.get().getCompanyId());
        companyUserRoleQw.eq(SysCompanyUserRole::getRoleId, role.getId());
        companyUserRoleQw.eq(SysCompanyUserRole::getCompanyUserId, adminUser.getId());
        //删除关系
        companyUserRoleMapper.delete(companyUserRoleQw);


        //5. 添加新的主管理员的身份
        SysCompanyUserRole companyUserRole = new SysCompanyUserRole();
        companyUserRole.setCompanyId(CurrentUserHolder.get().getCompanyId());
        companyUserRole.setRoleId(role.getId());
        companyUserRole.setCompanyUserId(companyUser.getId());

        companyUserRoleMapper.insert(companyUserRole);
    }

    @Autowired
    SysUserMapper userMapper;

    @Autowired
    SysDepartmentMapper departmentMapper;

    @Override
    public void handleParsedData(List<ExcelMember> memberList) {

        if(CollectionUtil.isNotEmpty(memberList)){
            for (ExcelMember excelMember : memberList) {
                //判断手机号和邮箱是否已经存在
                LambdaQueryWrapper<SysUser> userQw = new LambdaQueryWrapper<>();
                userQw.eq(SysUser::getMobile, excelMember.getMobile()).or().eq(SysUser::getEmail, excelMember.getEmail());

                Integer count = userMapper.selectCount(userQw);
                if(count > 0){
                    throw new NcException(ResponseEnum.USER_MOBILE_EMAIL_EXISTS);
                }

                //工号是否重复
                LambdaQueryWrapper<SysCompanyUser> companyUserLambdaQw = new LambdaQueryWrapper<>();
                companyUserLambdaQw.eq(SysCompanyUser::getWorkNumber, excelMember.getWorkNumber());

                Integer count1 = companyUserMapper.selectCount(companyUserLambdaQw);
                if(count1 > 0){
                    throw new NcException(ResponseEnum.WROK_NUM_EXISTS);
                }

                //组装 用户表的数据
                SysUser user = new SysUser();
                user.setUsername(excelMember.getName());
                user.setPassword(new BCryptPasswordEncoder().encode("123456")); //初始密码
                user.setEmail(excelMember.getEmail());
                user.setMobile(excelMember.getMobile());
                user.setStatus((short)1);
                user.setLastLoginCompanyId(CurrentUserHolder.get().getCompanyId());
                user.setCreateTime(new Date());

                userMapper.insert(user);


                //组装 员工表的数据
                SysCompanyUser companyUser = new SysCompanyUser();
                companyUser.setUserName(excelMember.getName());
                companyUser.setUserId(user.getId());
                companyUser.setEmail(excelMember.getEmail());
                companyUser.setEnable((short)1);
                companyUser.setPost(excelMember.getPosition());
                companyUser.setMobile(excelMember.getMobile());
                companyUser.setWorkNumber(excelMember.getWorkNumber()); //工号也不能重复
                companyUser.setRemark(excelMember.getDesc());
                companyUser.setTimeEntry(excelMember.getEntryTime());
                companyUser.setCompanyId(CurrentUserHolder.get().getCompanyId());
                companyUser.setCompanyName(CurrentUserHolder.get().getCompanyName());
                companyUser.setOfficeAddress(excelMember.getWorkAddr());
                companyUser.setCreateTime(new Date());
                //查询部门， 设置部门信息
                LambdaQueryWrapper<SysDepartment> departmentQw = new LambdaQueryWrapper<>();
                departmentQw.eq(SysDepartment::getCompanyId, CurrentUserHolder.get().getCompanyId());
                departmentQw.eq(SysDepartment::getName, excelMember.getDepartmentName());

                SysDepartment department = departmentMapper.selectOne(departmentQw);
                if(department != null){
                    companyUser.setDepartmentId(department.getId());
                    companyUser.setDepartmentName(department.getName());
                }

                companyUserMapper.insert(companyUser);

                //组装 员工和角色关系表的数据

                //根据角色名称获取 角色id
                LambdaQueryWrapper<SysRole> roleQw = new LambdaQueryWrapper<>();
                roleQw.eq(SysRole::getRoleName, excelMember.getRoleName());
                roleQw.eq(SysRole::getCompanyId, CurrentUserHolder.get().getCompanyId());

                SysRole role = roleMapper.selectOne(roleQw);
                if(role != null){
                    SysCompanyUserRole companyUserRole = new SysCompanyUserRole();
                    companyUserRole.setCompanyUserId(companyUser.getId());
                    companyUserRole.setCompanyId(CurrentUserHolder.get().getCompanyId());
                    companyUserRole.setRoleId(role.getId());
                    companyUserRoleMapper.insert(companyUserRole);
                }

            }
        }

    }

    @Override
    public SysCompanyUserDTO findCompanyUserByMobile(String mobile) {
        if(mobile == null){
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }
        LambdaQueryWrapper<SysCompanyUser> companyUserLambdaQw = new LambdaQueryWrapper<>();
        companyUserLambdaQw.eq(SysCompanyUser::getCompanyId, CurrentUserHolder.get().getCompanyId());
        companyUserLambdaQw.eq(SysCompanyUser::getMobile, mobile);

        SysCompanyUser companyUser = companyUserMapper.selectOne(companyUserLambdaQw);
        if(companyUser == null){
            throw new NcException(ResponseEnum.USER_NOT_FOUND);
        }
        return BeanHelper.copyProperties(companyUser,SysCompanyUserDTO.class);
    }

    @Override
    public PageResult<SysCompanyUserDTO> members(Integer page, Integer pageSize, Long departmentId, String keyword) {

        //存储当前部门的 子部门id的集合
        List<Long> departmentIds = new ArrayList<>();
        //添加当前部门id
        departmentIds.add(departmentId);
        //获取当前部门的 子部门id的集合
        this.queryChildDepartmentIds(departmentIds, departmentId);


        //获取对应的员工信息
        //创建page对象
        Page<SysCompanyUser> companyUserPage = new Page<>(page , pageSize);

        LambdaQueryWrapper<SysCompanyUser> companyUserQw = new LambdaQueryWrapper<>();
        companyUserQw.eq(SysCompanyUser::getCompanyId, CurrentUserHolder.get().getCompanyId());
        companyUserQw.in(SysCompanyUser::getDepartmentId, departmentIds);

        if(StrUtil.isNotEmpty(keyword)){
            companyUserQw.and(wrapper ->{
                wrapper.like(SysCompanyUser::getUserName, keyword)
                        .or().like(SysCompanyUser::getWorkNumber, keyword)
                        .or().like(SysCompanyUser::getMobile, keyword);
            });
        }

        //分页查询
        companyUserPage = companyUserMapper.selectPage(companyUserPage, companyUserQw);

        return new PageResult(companyUserPage.getTotal(), companyUserPage.getPages(), companyUserPage.getRecords());
    }

    @Override
    public void importData(MultipartFile excelFile) {
        if(excelFile != null){
            try {
                EasyExcel.read(excelFile.getInputStream(), ExcelMember.class, new ExcelMemberListener(this)).sheet(0).doRead();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else{
            throw new NcException(ResponseEnum.FILE_NOT_FOUND);
        }
    }

    @Override
    public Integer queryUserCountByDepartmentId(List<Long> departmentIds) {
        if(CollectionUtil.isNotEmpty(departmentIds)){
            List<Long> ids = new ArrayList<>();
            for (Long departmentId : departmentIds) {
                //把当前部门id添加到集合中
                ids.add(departmentId);
                //查询该部门的子部门的id集合
                this.queryChildDepartmentIds(ids, departmentId);
            }
            //去重
            ids = CollectionUtil.distinct(ids);

            //查询 该部门列表对应的员工信息
            LambdaQueryWrapper<SysCompanyUser> companyUserQw = new LambdaQueryWrapper<>();
            companyUserQw.eq(SysCompanyUser::getCompanyId, CurrentUserHolder.get().getCompanyId());
            companyUserQw.in(SysCompanyUser::getDepartmentId, ids);

            Integer count = companyUserMapper.selectCount(companyUserQw);

            return count;
        }
        return 0;
    }

    @Override
    public SysCompanyUserDTO queryAdminByCompanyId(Long companyId) {
        SysCompanyUser companyUser = companyUserMapper.queryCurrentAdmin(companyId);
        if(companyUser != null){
            return BeanHelper.copyProperties(companyUser, SysCompanyUserDTO.class);
        }
        return null;
    }

    public void queryChildDepartmentIds(List<Long> departmentIds, Long departmentId){
        LambdaQueryWrapper<SysDepartment> departmentWrapper = new LambdaQueryWrapper<>();
        departmentWrapper.eq(SysDepartment::getCompanyId, CurrentUserHolder.get().getCompanyId());
        departmentWrapper.eq(SysDepartment::getParentId, departmentId);
        List<SysDepartment> departmentList = departmentMapper.selectList(departmentWrapper);
        if(CollectionUtil.isNotEmpty(departmentList)){
            //取出部门集合中的部门id
            List<Long> ids = departmentList.stream().map(department -> {
                return department.getId();
            }).collect(Collectors.toList());
            departmentIds.addAll(ids);

            for (Long id : ids) {
                this.queryChildDepartmentIds(departmentIds , id);
            }
        }
    }
    /**
     * 根据id查询员工
     * @param companyUserId
     * @return
     */
    @Override
    public SysCompanyUserDTO queryCompanyUserById(Long companyUserId) {
        SysCompanyUser sysCompanyUser = companyUserMapper.selectById(companyUserId);
        return BeanHelper.copyProperties(sysCompanyUser, SysCompanyUserDTO.class);
    }
}
